/*
** philosophe.c for  in /home/lucas/projet/philosophe/laidfilauxzauphe
** 
** Made by Lucas Stefas
** Login   <stefas_l@epitech.net>
** 
** Started on  Sat Apr 30 10:06:18 2011 Lucas Stefas
** Last update Sat Apr 30 10:06:19 2011 Lucas Stefas
*/

#include <unistd.h>
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <pthread.h>
#include "plsp.h"


void		dodo(philosophe * self)
{
  baguette*	baguettes;

  has_free_baguette(self, 3);
  baguettes = self->look_for_a_baguette(self);
  if (baguettes)
    {
      self->add_baguette(self, baguettes);
      self->think(self);
    }
  else
    {
      printf("%u is sleeping.\n", self->id);
      usleep(100);
    }
}

void		add_baguette(philosophe *self, baguette *baguettes)
{
  if (!self->left_hand)
    self->left_hand = baguettes;
  else if (!self->right_hand)
    self->right_hand = baguettes;
}

void		remove_baguette(philosophe * self)
{
  if (self->left_hand)
    {
      self->left_hand->free(self->left_hand);
      self->left_hand = NULL;
      pthread_mutex_unlock(&self->table->looker);
    }
  if (self->right_hand)
    {
      self->right_hand->free(self->right_hand);
      self->right_hand = NULL;
      pthread_mutex_unlock(&self->table->looker);
    }
}

void		will_do(philosophe *self)
{
  struct timespec	tp;

  while (1)
    {
      tp = self->start;
      tp.tv_sec += TIME_DEATH;
      if (pthread_mutex_timedlock(&self->table->looker, &tp)
	  != ETIMEDOUT)
	{
	  if (self->left_hand && self->right_hand)
	    self->eat(self);
	  else if (self->left_hand || self->right_hand)
	    self->think(self);
	  else
	    self->sleep(self);
	}
      else
	{
	  pthread_mutex_unlock(&self->table->looker);
	  printf("philosophe %d dies\n", self->id);
	  break;
	}
    }
}

void*	run_philosophe(void *arg)
{
  philosophe*	self = (philosophe*)arg;

  printf("is waiting...\n");
  pthread_mutex_lock(&self->table->starter);
  printf("I'm now running says the %d philosophe.\n", self->id);
  pthread_mutex_unlock(&self->table->starter);
  clock_gettime(CLOCK_REALTIME, &self->start);
  will_do(self);
  return (NULL);
}
